/*
 * Description: 通信服务端基类，实现了服务端的基础通信功能。接口类。
 */
#ifndef GUEST_LINK_SERVICE
#define GUEST_LINK_SERVICE

#include <set>
#include <string>
#include <thread>
#include <mutex>
#include <vector>
#include "connect_common.h"
#include "link_base.h"
#include "guest_socket.h"
#include "thread_pool.h"
#include "log.h"
#include "error.h"

namespace COMMON {

constexpr char SERIAL_CLIENT_NAME[] = "serialClient";

class Service {
public:
    explicit Service(const std::string &name);
    virtual ~Service();
    /*******************************************************************************
      函 数 名		:  ParseProto
      功能描述		:  将target数据解析成call对象返回
      输入参数		:  target：需要封装的proto数据
      输出参数		:  将target数据封装到call返回
      返 回 值		:  None
    *******************************************************************************/
    void ParseProto(google::protobuf::MessageLite &target, Guest::protobuf::link::Call &call);

protected:

    /*******************************************************************************
      函 数 名		:  EstablishEventServer
      功能描述		:  创建事件响应服务，创建成功之后会响应客户端事件请求，从dispatch方法进行分发
      输入参数		:  socketInfo:socket路径
      输出参数		:  None
      返 回 值		:  成功返回0，失败返回-1
    *******************************************************************************/
    int EstablishEventServer(int port,
        const std::string& userId = "", const std::string& appId = "", const std::string& vmName = "");

    /*******************************************************************************
      函 数 名		:  Dispatch
      功能描述		:  分发客户端过来的事件。纯虚函数
      输入参数		:  call:call会提供调用相关信息：调用ID，参数
      输出参数		:  如果是同步调用需要提供返回值到res中,异步调用则可忽略
      返 回 值		:  None
    *******************************************************************************/
    virtual void Dispatch(Guest::protobuf::link::Call &call,
        Guest::protobuf::link::Result &res) = 0;
    virtual void Dispatch(Guest::protobuf::link::Call &call,
        Guest::protobuf::link::Result &res, const std::string &clientInfo);

    /*******************************************************************************
      函 数 名		:  OnConnected
      功能描述		:  分发客户端过来的链接事件。虚函数。可在此根据客户端名称管理客户端链接
      输入参数		:  connectName:客户端名称
      输出参数		:  None
      返 回 值		:  None
    *******************************************************************************/
    virtual void OnConnected(const std::string &connectName);

    /*******************************************************************************
      函 数 名		:  OnDisconnected
      功能描述		:  分发客户端过来的断链事件。虚函数。可在此根据客户端名称管理客户端断链事件
      输入参数		:  connectName:客户端名称
      输出参数		:  None
      返 回 值		:  None
    *******************************************************************************/
    virtual void OnDisconnected(const std::string &connectName);

    /*******************************************************************************
      函 数 名		:  SetReadTimeout
      功能描述		:  设置读数据超时时间，建议在链接建立通知中调用，灵活控制各链路超时时间（如：OnWriteStreamConnected）
      输入参数		:  timeout:超时时间，默认-1:阻塞，单位:s
      输出参数		:  None
      返 回 值		:  None
    *******************************************************************************/
    void SetReadTimeout(int timeout);

    /*******************************************************************************
      函 数 名		:  CloseEventServer
      功能描述		:  关闭事件通道
      输出参数		:  None
      返 回 值		:  成功返回0,失败返回-1
    *******************************************************************************/
    int CloseEventServer();

private:
    static void HandleEvent(const std::shared_ptr<MsgSock> &msgSock, void *arg);
    static void HandleConnectSerial(const std::shared_ptr<MsgSock> &server, void *arg);
    int SendMessage(const std::shared_ptr<MsgSock> &msgSock, MessageType type,
        const google::protobuf::MessageLite &message) const;
    int CreateServer(SocketInfo info, std::shared_ptr<MsgSock> &msgSock);
    void ConnectEventNotify(const std::string &connectName, const std::shared_ptr<MsgSock> &subServer);

    bool HandleConnectMode(const std::shared_ptr<MsgSock> &subServer, void *arg, const std::string &mode,
                           const std::string &name) const;
#if (defined _WIN32)
    void HandleEventTask(const std::shared_ptr<MsgSock> &subServer, void *arg) const;
#endif

private:
    std::string m_name {};
    std::shared_ptr<MsgSock> m_msgSerialSock = nullptr;
    std::map<int, std::string> m_sockMap = {};
    std::mutex m_initLock = {};
    std::map<int, std::shared_ptr<MsgSock>> m_subSockMap = {};
    int m_curTimeout = DEFAULT_TIME_OUT;
    COMMON::ThreadPool m_threadPool {5}; // 默认线程数量5 注意: 必须是第一个摧毁的成员

    friend void DispatchAndReply(Guest::protobuf::link::Call call, Service *service, int messageType,
      const std::shared_ptr<MsgSock> &msgSock);
};
}
#endif // GUEST_LINK_SERVICE
